﻿using NexTrackDesktop.Media;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.IO;
using System.Collections.Generic;

namespace NexTrackDesktopTest
{
    
    
    /// <summary>
    ///This is a test class for LibraryTest and is intended
    ///to contain all LibraryTest Unit Tests
    ///</summary>
    [TestClass()]
    public class LibraryTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for AddFile
        ///</summary>
        [TestMethod()]
        public void AddFileTest()
        {
            Library target = new Library(new FileNameTagger());
            Uri fileA = new Uri(@"F:\Some\Path\Best File.mp4");
            Uri fileB = new Uri(@"F:\Better\Path\Worse File.mp4");
            Uri fileC = new Uri(@"F:\Old_Path\Other File.mp4");

            target.AddFile(fileA);
            target.AddFile(fileB);
            target.AddFile(fileC);

            var actualItems = target.Items;

            Assert.AreEqual(3, actualItems.Count, "adding 3 distinct files, 3 items");

            Assert.AreEqual(1, actualItems.Count(s => s.Location == fileA));
            Assert.AreEqual(1, actualItems.Count(s => s.Location == fileB));
            Assert.AreEqual(1, actualItems.Count(s => s.Location == fileC));

            target.AddFile(fileB);

            Assert.AreEqual(3, actualItems.Count, "adding 3 distinct files with 1 duplicate should result in 3 items");
        }

        /// <summary>
        ///Tests recursive action of addFolderRecursive
        ///</summary>
        [TestMethod()]
        public void addFolderRecursiveTest()
        {
            string[] test_files = { "01.mp3", "02.mp3", "f1\\03.mp3", "f2\\04.mp3" };
            CreateAndTestFolders(test_files);
        }

        /// <summary>
        ///Tests the file type action of addFolderRecursive
        ///</summary>
        [TestMethod()]
        public void addFolderFileTypes()
        {
            //ask for all supported search extensions
            string[] test_files = Library.searchExtensions.Select(ext => "song" + ext).ToArray();

            //test them
            CreateAndTestFolders(test_files);
        }


        /// <summary>
        /// Creates empty files given in a test directory in the the temp folder and then adds that directory recursively
        /// </summary>
        /// <param name="test_files"></param>
        private void CreateAndTestFolders(string[] test_files)
        {
            ITagger tagger = new FileNameTagger();
            Library target = new Library(tagger);

            string test_dir = Path.Combine(Path.GetTempPath(), "nt_test");

            if (Directory.Exists(test_dir))
                Directory.Delete(test_dir, true);

            for (int i = 0; i < test_files.Length; i++)
            {
                string path = test_files[i] = Path.Combine(test_dir, test_files[i]);

                if (!Directory.Exists(Path.GetDirectoryName(path)))
                    Directory.CreateDirectory(Path.GetDirectoryName(path));

                using (var tmp = File.Create(path)) ;
            }

            target.addFolderRecursive(test_dir);

            string[] actual_files = target.Items.Select(s => s.Location.LocalPath).OrderBy(s => s).ToArray();

            test_files = test_files.OrderBy(s => s).ToArray();

            //tests that all files are added recursively
            for (int i = 0; i < test_files.Length; i++)
            {
                Assert.AreEqual(actual_files[i], test_files[i]);
            }
        }

        // *********************************************************************************
        // Tests for loading and unloading xml
        //

        List<Song> BasicTestSongs = new List<Song>
        {
            new Song() { Album = "Album 1", Artist = "Artist 1", Title = "Title 1", Location = new Uri("C:\\Music\\Song 1.mp3"),
                Length = new TimeSpan(1,1,1), AlbumArtSource = new Uri("http://www.example.com/art_1.jpg"), SongID = "1" },
            new Song() { Album = "Album 2", Artist = "Artist 2", Title = "Title 2", Location = new Uri("C:\\Music\\Song 2.mp3"),
                Length = new TimeSpan(2,2,2), AlbumArtSource = new Uri("http://www.example.com/art_2.jpg"), SongID = "2" },
            new Song() { Album = "Album 3", Artist = "Artist 3", Title = "Title 3", Location = new Uri("C:\\Music\\Song 3.mp3"),
                Length = new TimeSpan(3,3,3), AlbumArtSource = new Uri("http://www.example.com/art_3.jpg"), SongID = "3" },
            new Song() { Album = "Album 4", Artist = "Artist 4", Title = "Title 4", Location = new Uri("C:\\Music\\Song 4.mp3"),
                Length = new TimeSpan(4,4,4), AlbumArtSource = new Uri("http://www.example.com/art_4.jpg"), SongID = "4" },
        };

        string BasicTestXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
            "<ArrayOfSong xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n" +
@"  <Song>
    <Artist>Artist 1</Artist>
    <Album>Album 1</Album>
    <Title>Title 1</Title>
    <SongID>1</SongID>
    <Location>file:///C:/Music/Song 1.mp3</Location>
    <AlbumArtSource>http://www.example.com/art_1.jpg</AlbumArtSource>
    <Length>36610000000</Length>
  </Song>
  <Song>
    <Artist>Artist 2</Artist>
    <Album>Album 2</Album>
    <Title>Title 2</Title>
    <SongID>2</SongID>
    <Location>file:///C:/Music/Song 2.mp3</Location>
    <AlbumArtSource>http://www.example.com/art_2.jpg</AlbumArtSource>
    <Length>73220000000</Length>
  </Song>
  <Song>
    <Artist>Artist 3</Artist>
    <Album>Album 3</Album>
    <Title>Title 3</Title>
    <SongID>3</SongID>
    <Location>file:///C:/Music/Song 3.mp3</Location>
    <AlbumArtSource>http://www.example.com/art_3.jpg</AlbumArtSource>
    <Length>109830000000</Length>
  </Song>
  <Song>
    <Artist>Artist 4</Artist>
    <Album>Album 4</Album>
    <Title>Title 4</Title>
    <SongID>4</SongID>
    <Location>file:///C:/Music/Song 4.mp3</Location>
    <AlbumArtSource>http://www.example.com/art_4.jpg</AlbumArtSource>
    <Length>146440000000</Length>
  </Song>
</ArrayOfSong>";

        [TestMethod()]
        public void BasicSaveTest()
        {
            string dest = Path.GetTempFileName();
            LibraryXMLFileSource target = new LibraryXMLFileSource(dest);

            target.Save(BasicTestSongs);
            string result = File.ReadAllText(dest);

            Assert.AreEqual(BasicTestXml, result);
        }

        [TestMethod()]
        public void BasicLoadTest()
        {
            string src = Path.GetTempFileName();
            File.WriteAllText(src, BasicTestXml);

            LibraryXMLFileSource target = new LibraryXMLFileSource(src);
            var songs = target.Load();

            Util.AssertAllEqual(BasicTestSongs, songs);
        }

        [TestMethod()]
        public void SaveLoadTest()
        {
            string srcdest = Path.GetTempFileName();

            LibraryXMLFileSource target = new LibraryXMLFileSource(srcdest);
            target.Save(BasicTestSongs);
            var songs = target.Load();

            Util.AssertAllEqual(BasicTestSongs, songs);
        }
    }
}
